package org.springblade.modules.digitalization.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.sanselan.ImageInfo;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.digitalization.entity.ManageRsdamlEntity;
import org.springblade.modules.digitalization.wrapper.UserDaRs;

import org.springblade.modules.digitalization.wrapper.UserInfoRs;
import org.springblade.modules.digitalization.wrapper.UserMenuRs;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.text.ParseException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

@Slf4j
public class DaUtils {
	public static final Integer NO_E_ARCHIVE = 0;
	public static final Integer E_ARCHIVE = 1;

	public static final String IMG_DATA = "图像数据";
	public static final String NORMAL_IMG_DATA = "原始图像数据";
	public static final String HIGH_IMG_DATA = "优化图像数据";


	public static void convertChineseRightQuote(ManageRsdamlEntity rsdaml) {
		if (StringUtils.isNotBlank(rsdaml.getRsdaml004())) {
			rsdaml.setRsdaml004(StringUtils.replace(rsdaml.getRsdaml004(), "&quot;", "”"));
		}
	}

	public static boolean compressFolder(String folderPath, String zipFilePath) {
		try {
			File folder = new File(folderPath);
			if (!folder.exists() || !folder.isDirectory()) {
				return false; // 文件夹不存在或者不是一个文件夹，压缩失败
			}

			FileOutputStream fos = new FileOutputStream(zipFilePath);
			ZipOutputStream zos = new ZipOutputStream(fos);

			compressFolder(folder, folder.getName(), zos);

			zos.close();
			fos.close();

			return true; // 压缩成功
		} catch (IOException e) {
			e.printStackTrace();
			return false; // 压缩失败
		}
	}

	private static void compressFolder(File folder, String parentFolderName, ZipOutputStream zos) throws IOException {
		File[] files = folder.listFiles();
		byte[] buffer = new byte[1024];
		int bytesRead;

		for (File file : files) {
			if (file.isDirectory()) {
				compressFolder(file, parentFolderName + "/" + file.getName(), zos);
			} else {
				FileInputStream fis = new FileInputStream(file);
				zos.putNextEntry(new ZipEntry(parentFolderName + "/" + file.getName()));

				while ((bytesRead = fis.read(buffer)) != -1) {
					zos.write(buffer, 0, bytesRead);
				}

				fis.close();
				zos.closeEntry();
			}
		}
	}

	public static void unzipFile(String sourceFile, String destinationDir) throws IOException {
		try (ZipFile zipFile = new ZipFile(sourceFile)) {
			Enumeration<? extends ZipEntry> entries = zipFile.entries();
			while (entries.hasMoreElements()) {
				ZipEntry entry = entries.nextElement();
				Path path = new File(destinationDir, entry.getName()).toPath();
				if (!entry.isDirectory()) {
					try (InputStream inputStream = zipFile.getInputStream(entry)) {
						Path parent = path.getParent();
						if (!Files.exists(parent)) {
							Files.createDirectories(parent);
						}
						Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
					}
				} else {
					Files.createDirectories(path);
				}
			}
		}
	}

	// 加密方法
	public static void encryptImage(String key, File inputFile, File outputFile) throws Exception {
		// 创建AES加密算法实例
		Cipher cipher = Cipher.getInstance("AES");
		// 创建AES加密算法的密钥
		SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
		// 初始化加密算法实例
		cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
		// 创建输入流读取加密后的图片文件
		BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile));
		// 创建输出流写入解密后的图片文件
		BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
		// 加密图片文件
		byte[] buffer = new byte[4096];
		int len;
		while ((len = inputStream.read(buffer)) > 0) {
			byte[] encryptedBytes = cipher.update(buffer, 0, len);
			outputStream.write(encryptedBytes);
		}
		byte[] encryptedBytes = cipher.doFinal();
		outputStream.write(encryptedBytes);
		// 关闭输入输出流
		inputStream.close();
		outputStream.close();
	}

	// 解密方法
	public static void decryptImage(String key, File inputFile, File outputFile) throws Exception {
		// 创建AES解密算法实例
		Cipher cipher = Cipher.getInstance("AES");
		// 创建AES解密算法的密钥
		SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
		// 初始化解密算法实例
		cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
		// 创建输入流读取加密后的图片文件
		BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile));
		// 创建输出流写入解密后的图片文件
		BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
		// 解密图片文件
		byte[] buffer = new byte[4096];
		int len;
		while ((len = inputStream.read(buffer)) > 0) {
			byte[] decryptedBytes = cipher.update(buffer, 0, len);
			outputStream.write(decryptedBytes);
		}
		byte[] decryptedBytes = cipher.doFinal();
		outputStream.write(decryptedBytes);
		// 关闭输入输出流
		inputStream.close();
		outputStream.close();
	}

	public static Date parseDate(String createDate) throws ParseException {
		createDate = createDate.replaceAll("-", "");
		Date parseDate = null;
		if (!createDate.contains("-")) {
			if (createDate.length() == 6) {
				parseDate = DateUtil.parse(createDate, "yyyyMM");
			} else if (createDate.length() == 8) {
				parseDate = DateUtil.parse(createDate, "yyyyMMdd");
			}
		}
		return parseDate;
	}

	public static UserDaRs checkZipFileStructIsComplete(String targetFilePath) {
		//         --图像数据
//              --原始图像数据
//              --优化图像数据
//         --xml文件
		String filePath = cn.hutool.core.io.FileUtil.getParent(targetFilePath, 1);
		String fileName = FileUtil.getNameWithoutExtension(targetFilePath);
		String rootFileName = FileUtil.getNameWithoutExtension(targetFilePath);
		String picDataPath = StringUtils.join(filePath, File.separator, rootFileName, File.separator, IMG_DATA);
		String normalPicDataPath = StringUtils.join(filePath, File.separator, rootFileName, File.separator, IMG_DATA, File.separator, NORMAL_IMG_DATA);
		String highPicDataPath = StringUtils.join(filePath, "/", rootFileName, "/", IMG_DATA, "/", HIGH_IMG_DATA);
		String xmlFilePath = StringUtils.join(filePath, "/", rootFileName, "/", rootFileName, ".xml");
		if (!cn.hutool.core.io.FileUtil.exist(filePath + File.separator + rootFileName)) {
			throw new ServiceException(String.format("%s档案数据包中无%s文件夹", fileName, rootFileName));
		}
		if (!cn.hutool.core.io.FileUtil.exist(picDataPath)) {
			log.error("档案数据包解析失败，失败原因：{}", fileName + "档案数据包中无图像数据文件夹");
			throw new ServiceException(fileName + "档案数据包中无图像数据文件夹");
		}
		if (!cn.hutool.core.io.FileUtil.exist(normalPicDataPath)) {
			log.error("档案数据包解析失败，失败原因：{}", fileName + "档案数据包中无原始图像数据文件夹");
			throw new ServiceException(fileName + "档案数据包中无原始图像数据文件夹");
		}
		if (!cn.hutool.core.io.FileUtil.exist(highPicDataPath)) {
			log.error("档案数据包解析失败，失败原因：{}", fileName + "档案数据包中无优化图像数据文件夹");
			throw new ServiceException(fileName + "档案数据包中无优化图像数据文件夹");
		}
		// 这里判断是根目录是否存在
		if (Func.isBlank(rootFileName)) {
			log.error("获取xml文件失败，失败原因：{}", fileName + "档案数据包中无xml文件");
			throw new ServiceException(fileName + "档案数据包中无xml文件");
		}
		log.info("档案" + rootFileName + "中XML文件的路径为：" + xmlFilePath);
		if (!cn.hutool.core.io.FileUtil.exist(xmlFilePath)) {
			log.error("解压xml文件失败，失败原因：{}", "系统未找到指定的" + rootFileName + ".xml文件");
			throw new ServiceException("解压xml文件失败，失败原因：{}" + "系统未找到指定的" + rootFileName + ".xml文件");
		}

		// 获取xml文件内容
		UserDaRs userByXml = getUserByXml(xmlFilePath);


		// 3、处理xml校验结果
		return userByXml;

	}

	static UserDaRs getUserByXml(String xmlPath) throws ServiceException {
		UserDaRs userDaRs = new UserDaRs();
		UserInfoRs userInfoRs = new UserInfoRs();

		// Create a File object for the XML file
		File xmlFile = new File(xmlPath);

		// Create a DocumentBuilderFactory object
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

		// Create a DocumentBuilder object
		DocumentBuilder dBuilder = null;
		try {
			dBuilder = dbFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new ServiceException("xml 文件问题");
		}

		// Parse the XML file and create a Document object
		Document doc = null;
		try {
			doc = dBuilder.parse(xmlFile);
		} catch (SAXException e) {
			throw new ServiceException("xml 文件问题");
		} catch (IOException e) {
			throw new ServiceException("xml 文件问题");
		}

		// Normalize the Document object
		doc.getDocumentElement().normalize();

		// Get the root element of the XML file
		Element root = doc.getDocumentElement();

		// Get the "人员基本信息" element
		Element info = (Element) root.getElementsByTagName("人员基本信息").item(0);

		// Get the value of the "姓名" element
		String name = info.getElementsByTagName("姓名").item(0).getTextContent();

		// Get the value of the "性别" element
		String gender = info.getElementsByTagName("性别").item(0).getTextContent();

		// Get the value of the "民族" element
		String nation = info.getElementsByTagName("民族").item(0).getTextContent();

		// Get the value of the "出生日期" element
		String birthdate = info.getElementsByTagName("出生日期").item(0).getTextContent();

		// Get the value of the "公民身份号码" element
		String id = info.getElementsByTagName("公民身份号码").item(0).getTextContent();
		userInfoRs.setUserName(name);
		userInfoRs.setIdCard(id);
		userInfoRs.setBirthDay(birthdate);
		userInfoRs.setMz(nation);
		userInfoRs.setSex(gender);
		userDaRs.setUserInfo(userInfoRs);
		if (Func.isBlank(name) || Func.isBlank(id)) {
			throw new ServiceException("姓名或者身份证号不可为空");
		}
		// Get the 目录信息 element
		Element catalogElement = (Element) doc.getElementsByTagName("目录信息").item(0);

		// Get all the 档案目录条目 elements
		NodeList itemList = catalogElement.getElementsByTagName("档案目录条目");

		// Loop through each 档案目录条目 element
		for (int i = 0; i < itemList.getLength(); i++) {
			Node itemNode = itemList.item(i);
			if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
				UserMenuRs userMenuRs = new UserMenuRs();
				userDaRs.getMenus().add(userMenuRs);
				Element itemElement = (Element) itemNode;

				// Get the 类号 element
				String classNumber = itemElement.getElementsByTagName("类号").item(0).getTextContent();

				// Get the 序号 element
				String serialNumber = itemElement.getElementsByTagName("序号").item(0).getTextContent();

				// Get the 材料名称 element
				String materialName = itemElement.getElementsByTagName("材料名称").item(0).getTextContent();

				// Get the 材料形成时间 element
				String materialCreationTime = itemElement.getElementsByTagName("材料形成时间").item(0).getTextContent();

				// Get the 页数 element
				String pageCount = itemElement.getElementsByTagName("页数").item(0).getTextContent();

				userMenuRs.setClassNum(classNumber);
				userMenuRs.setCaiLiaoName(materialName);
				try {
					if (Func.isNotEmpty(materialCreationTime)) {
						userMenuRs.setCreateAt(parseDate(materialCreationTime));
					}
				} catch (ParseException e) {
					throw new ServiceException("材料制成时间格式错误：" + materialCreationTime);
				}
				userMenuRs.setPageNum(Integer.valueOf(pageCount));
				userMenuRs.setIdNum(serialNumber);
				if (Func.isBlank(classNumber) || Func.isBlank(materialName) || Func.isBlank(serialNumber) || Func.isBlank(pageCount)) {
					throw new ServiceException(String.format("目录项有问题:类号 %s,序号：%s,材料名称 %s,页数 %s", classNumber, serialNumber, materialName, pageCount));
				}
				// Get the 原始图像数据_Text elements
				NodeList originalImageList = itemElement.getElementsByTagName("原始图像数据_Text");

				// Loop through each 原始图像数据_Text element
				for (int j = 0; j < originalImageList.getLength(); j++) {
					Node originalImageNode = originalImageList.item(j);
					if (originalImageNode.getNodeType() == Node.ELEMENT_NODE) {
						Element originalImageElement = (Element) originalImageNode;
						// Get the 原始图像数据_Text value
						String originalImage = originalImageElement.getTextContent();
						userMenuRs.getOrgImgs().add(originalImage);
					}
				}

				// Get the 优化图像数据_Text elements
				NodeList optimizedImageList = itemElement.getElementsByTagName("优化图像数据_Text");

				// Loop through each 优化图像数据_Text element
				for (int j = 0; j < optimizedImageList.getLength(); j++) {
					Node optimizedImageNode = optimizedImageList.item(j);
					if (optimizedImageNode.getNodeType() == Node.ELEMENT_NODE) {
						Element optimizedImageElement = (Element) optimizedImageNode;
						// Get the 优化图像数据_Text value
						String optimizedImage = optimizedImageElement.getTextContent();
						userMenuRs.getHdImgs().add(optimizedImage);
					}
				}
				//页码校验
				if (userMenuRs.getPageNum() != 0) {
					if (userMenuRs.getPageNum() != userMenuRs.getOrgImgs().size()) {
						throw new ServiceException("原始材料页数与页码不符" + userMenuRs.getCaiLiaoName());
					}
					if (userMenuRs.getPageNum() != userMenuRs.getHdImgs().size()) {
						throw new ServiceException("高清材料页数与页码不符" + userMenuRs.getCaiLiaoName());
					}
				}
				// 图片校验主要是1. 图片存在性校验 2 300dpi校验 3 dip获取失败  4. 同名文件错误
				checkImgFile(true, userMenuRs.getHdImgs(), xmlPath);
			}
		}
		return userDaRs;
	}

	private static void checkImgFile(boolean isHd, List<String> imgs, String xmlPath) {
		String parent = cn.hutool.core.io.FileUtil.getParent(xmlPath, 1);
		if (isHd) {
			parent += File.separator + IMG_DATA + File.separator + HIGH_IMG_DATA;
		} else {
			parent += File.separator + IMG_DATA + File.separator + NORMAL_IMG_DATA;
		}
		Set<String> colloect = new HashSet<>();

		for (String img : imgs) {
			if (StringUtils.isBlank(img) || StringUtils.equals(img, "null") || img.equals("/")) {
				throw new ServiceException("图片路径或名称异常：" + img);
			}
			if (img.contains("\\")) {
				img = img.replaceFirst("\\\\", "");
			}
			if (img.contains("/")) {
				img = img.replaceFirst("/", "");
			}
			if (colloect.contains(img)) {
				throw new ServiceException("存在同名文件：" + img);
			} else {
				colloect.add(img);
			}
			String pictureFile = parent + File.separator + img;
			if (!cn.hutool.core.io.FileUtil.exist(pictureFile)) {
				throw new ServiceException("图片文件不存在：" + img);
			}
			// 校验图片dpi是否不小于300

			ImageInfo imageInfo = null;
			try {
				imageInfo = Sanselan.getImageInfo(new File(pictureFile));
			} catch (IOException | ImageReadException e) {
				throw new ServiceException(String.format("图片%s信息读取失败:%s", img, e.getMessage()));
			}
			// 图像dpi获取失败则返回-1
			int physicalWidthDpi = imageInfo.getPhysicalWidthDpi();
			int physicalHeightDpi = imageInfo.getPhysicalHeightDpi();
			if (physicalWidthDpi == -1 || physicalHeightDpi == -1) {
				throw new ServiceException(img + ":dip 无法获取");
			} else if (physicalWidthDpi < 300 || physicalHeightDpi < 300) {
				throw new ServiceException(img + ":dip<300");
			}

		}

	}

	public static String toDataStr(Date date) {
		if (date == null) {
			return "";
		}
		return DateUtil.format(date, "yyyyMMdd");
	}

	public static Date getDate(String dateStr) {
		if (StringUtils.isBlank(dateStr)) {
			return null;
		}

		// 年
		if (StringUtils.length(dateStr) == 4) {
			return DateUtil.parse(dateStr, "yyyy");
		}

		// 年月
		if (StringUtils.length(dateStr) == 6) {
			return DateUtil.parse(dateStr, "yyyyMM");
		}

		// 年月
		if (StringUtils.length(dateStr) == 8) {
			return DateUtil.parse(dateStr, "yyyyMMdd");
		}
		return null;
	}

	public static void main3(String[] args) throws Exception {
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			UserDaRs userByXml = getUserByXml("E:\\receiveDa\\receiveUpdateZippath\\王向恒130528199911131233\\王向恒130528199911131233.xml");
			System.out.println(userByXml);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("Total time taken: " + (endTime - startTime) / 1000 + " milliseconds");

//		System.out.println(FileUtil.getNameWithoutExtension("王向恒130528199911131233.zip"));
//		String sourceFile = "E:\\receiveDa\\receiveZippath\\王向恒130528199911131233.zip";
//		String destinationDir = "E:\\receiveDa\\receiveUpdateZippath";
////		 destinationDir = "E:\\receiveDa\\receiveArchivePath";
//		long startTime = System.currentTimeMillis();
//		for (int i = 0; i < 20; i++) {
////			unzipFile(sourceFile, destinationDir);
//			cn.hutool.core.util.ZipUtil.unzip(sourceFile, destinationDir, CharsetUtil.CHARSET_GBK);
//		}
//		long endTime = System.currentTimeMillis();
//		System.out.println("Total time taken: " + (endTime - startTime) / 1000 + " milliseconds");
//		String key = "1234567890123456";
//		long startTime = System.currentTimeMillis();
//		for (int i = 0; i < 1000; i++) {
//			encryptImage(key, new File("E:\\receiveDa\\receiveArchivePath\\王向恒130528199911131233\\图像数据\\原始图像数据\\10-1-010.jpg"), new File("E:\\receiveDa\\receiveArchivePath\\王向恒130528199911131233\\图像数据\\原始图像数据\\10-1-010en.jpg"));
//			decryptImage(key,new File("E:\\receiveDa\\receiveArchivePath\\王向恒130528199911131233\\图像数据\\原始图像数据\\10-1-010en.jpg"),new File("E:\\receiveDa\\receiveArchivePath\\王向恒130528199911131233\\图像数据\\原始图像数据\\10-1-010de.jpg"));
//		}
//		long endTime = System.currentTimeMillis();
//		System.out.println("Total time taken: " + (endTime - startTime) / 1000 + " milliseconds");
	}

	public static void deleteFolder(File folder) {
		if (folder.isDirectory()) {
			File[] files = folder.listFiles();
			if (files != null) {
				for (File file : files) {
					deleteFolder(file);
				}
			}
		}
		folder.delete();
	}

	public static void main(String[] args) {
//		String folderPath = "E:\\receiveDa\\web\\gbPath\\3f797134-4b50-45c0-a219-ce29e460de95";
//		String zipFilePath = "E:\\receiveDa\\web\\gbPath\\output.zip";
//
//		boolean result = compressFolder(folderPath, zipFilePath);
//		if (result) {
//			System.out.println("压缩成功");
//		} else {
//			System.out.println("压缩失败");
//		}
		String input = "This is a \"test\" string with \"quotes\".";

		// 使用正则表达式匹配并替换英文引号为中文引号
		// 先把左边的引号替换为中文左引号
		String output = input.replaceAll("\"(.*?)\"", "“$1”");


		// 输出结果
		System.out.println(input);
		System.out.println(output);


	}

}
